package com.xbjtech.controller;

import java.util.*;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.constraints.NotBlank;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.google.code.kaptcha.Constants;
import com.xbjtech.redis.RedisUtils;
import com.xbjtech.shiro.MobileYzmToken;
import com.xbjtech.util.SmsUtils;
import com.xbjtech.util.StringUtils;

@Controller
@Validated
public class LoginController {
	
	@Autowired
	RedisUtils redisUtils;
	
	@GetMapping("/login")
	public String login() {

		return "login";
	}
	
	@PostMapping("/login")
	public String login(
			@RequestParam(required = true) 
			@NotBlank(message = "用户名不能为空")
			String username, 
			@RequestParam(required = true) 
			@NotBlank(message = "密码不能为空")
			String password, 
			@RequestParam(required = true) 
			@NotBlank(message = "验证码不能为空")
			String code,
			Boolean rememberMe,
			Model model) {
		System.out.println("code:" + code);
		
		// 做服务器端校验
		Subject subject = SecurityUtils.getSubject();
		String sessionCode = (String) subject.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
		if (!code.equalsIgnoreCase(sessionCode)) {
			model.addAttribute("error", "验证码不正确");
			return "login";
		}
		
		UsernamePasswordToken token = new UsernamePasswordToken(username, password);
		token.setRememberMe(rememberMe == null ? false : rememberMe);
		try {
			subject.login(token);
			return "redirect:/index";
		} catch (UnknownAccountException ex) {
			ex.printStackTrace();
			// TODO: 表示用户名不存在
			model.addAttribute("error", ex.getMessage());
		} catch (IncorrectCredentialsException e) {
			e.printStackTrace();
			// TODO: 表示密码不正确
			model.addAttribute("error", "密码不正确");
		} catch (AuthenticationException e) {
			// TODO: handle exception
			e.printStackTrace();
			model.addAttribute("error", "登录失败，请稍候再试");
		}
		return "login";
	}
	
	@ExceptionHandler({ ConstraintViolationException.class })
	public ModelAndView handlerEx(ConstraintViolationException ex) {
		// 处理异常的实现
		ModelAndView mv = new ModelAndView("login");
		Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
		Iterator<ConstraintViolation<?>> iterator = constraintViolations.iterator();
		if (iterator.hasNext()) {
			ConstraintViolation<?> next = iterator.next();
			mv.addObject("error", next.getMessage());
		}
		return mv;
	}
	
	@PostMapping(
			value = "/sendcode", 
			produces = "application/json;charset=utf8"
			)
	@ResponseBody
	public String sendcode(
			@RequestParam(required = true)
			String mobile) {
		// 说明肯定拿到了一个手机号
		String code = StringUtils.randomString(4);
		Map<String, String> map = new HashMap<>();
		map.put("code", code);
		redisUtils.set(mobile.getBytes(), code.getBytes(), 10 * 60);
		boolean sendSmsFlag = SmsUtils.sendSms(mobile, "492365", map);
		if (sendSmsFlag) {
			return "{\"success\":\"true\"}";
		}
		return "{\"success\":\"false\"}";
	}
	
	@PostMapping("/mobilelogin")
	public String mobilelogin(
			String mobile,
			String yzm, Model model
			) {
		System.out.println(mobile + "======" + yzm);
		// 认证
		MobileYzmToken token = new MobileYzmToken(mobile, yzm);
		Subject subject = SecurityUtils.getSubject();
		try {
			subject.login(token);
			return "redirect:/index";
		} catch (UnknownAccountException ex) {
			ex.printStackTrace();
			model.addAttribute("error", ex.getMessage());
		} catch (IncorrectCredentialsException e) {
			e.printStackTrace();
			model.addAttribute("error", "验证码不正确");
		} catch (AuthenticationException e) {
			// TODO: handle exception
			e.printStackTrace();
			model.addAttribute("error", "登录失败，请稍候再试");
		}
		return "login";
	}
	
	@ExceptionHandler({Throwable.class})
	public String ex(Throwable ex) {
		ex.printStackTrace();
		return "login";
	}
	
//	@GetMapping("/logout")
//	public String logout() {
//		SecurityUtils.getSubject().logout();
//		return "login";
//	}

}
